<?php
declare(strict_types=1);

namespace LowCode\Core;

use LowCode\Asset;
use LowCode\Settings;
use mindplay\vite\Manifest as ViteManifest;
use Smarty\Exception;

class Manifest
{
    private static Manifest $instance;

    protected bool|string $isDev = false;
    protected string $title = "Admin";
    protected string $lang = "en";
    protected string $manifest_path = "./build/manifest.json";
    protected string $base_path = "./build/";

    protected array $appConfig = [];
    protected array $entries = ["src/main.ts"];

    private array $globals = [];


    public function __construct(array $config = [])
    {
        $this->appConfig = $config;
    }

    public static function factory(array $config = []): Manifest
    {
        if (!isset(self::$instance) || !(self::$instance instanceof self)) {
            self::$instance = new self($config);
        }else{
            self::$instance->setConfig($config);
        }
        return self::$instance;
    }

    public function setConfig(array $config = []): static
    {
        $this->appConfig = array_merge($this->appConfig, $config);
        return $this;
    }

    /**
     * @return array
     */
    public function getConfig(): array
    {
        return $this->appConfig;
    }

    public function setGlobals(array $globals = []): static
    {
        $this->globals = array_merge($this->globals, $globals);
        return $this;
    }

    /**
     * @return array
     */
    public function getGlobals(): array
    {
        return $this->globals;
    }

    public function setIsDev(bool $isDev): static
    {
        $this->isDev = $isDev;
        return $this;
    }

    /**
     * @return bool
     */
    public function getDev(): bool
    {
        return $this->isDev;
    }

    public function setManifestPath(string $path): static
    {
        $this->manifest_path = $path;
        return $this;
    }

    /**
     * @return string
     * @throws Exception
     */
    public function render(): string
    {
        $admin = Admin::factory();
        $appId = "app_".uniqid();
        $viteClass = "\Illuminate\Support\Facades\Vite";
        $isVite = isRunInLaravel() && class_exists($viteClass);
        $settings = Settings::make()->toArray();
        $this->appConfig['settings'] = array_merge($this->appConfig['settings'],$settings);
        $appConfig = json_encode($this->appConfig, JSON_UNESCAPED_UNICODE);
        $globals = json_encode($this->getGlobals(), JSON_UNESCAPED_UNICODE);
        $heads = [Asset::loadCss(), Asset::loadJs()];
        if ($isVite){
            $buildDir = $admin->getManifestDir();
            $heads[] = $viteClass::useHotFile(public_path('hot'))
                ->useBuildDirectory($buildDir) // 自定义构建目录...
                ->useManifestFilename('manifest.json') // 自定义清单文件名...
                ->withEntryPoints(...$this->entries)->toHtml();
        }else{
            $vite = new ViteManifest($this->isDev, $this->manifest_path, $this->base_path);
            $tags = $vite->createTags(...$this->entries);
            $heads[] = $tags->preload;
            $heads[] = $tags->css;
            $heads[] = $tags->js;
        }
        $head = implode("\n",$heads);
        $data = [
            'apiUrl'=>$this->appConfig['baseURL'],
            'appConfig'=>$appConfig,
            'lang'=>$this->appConfig['lang'],
            'title'=>$this->appConfig['title'],
            'globals'=>$globals,
            'head'=>$head,
            'appId'=>$appId,
        ];
        $view = new View(Admin::getTemplatePath());
        return $view->render("layout.tpl", $data);
    }
}
